OAuth 2.0 授權流程裡,關注的重點只有兩個:
其他細節就不是 OAuth 2.0 授權流程所關注的,如:資源伺服器如何驗證 Access Token,或是授權伺服器如何做身分驗證等。Hydra 的目的也不是在解決這些問題,而是將授權流程與這些細節很好地切分,達到關注點分離的效果,這也是為何第一天提到 Hydra 是一個職責單一的微服務,因為它要處理的領域確實是明確且獨立的。
因為 OAuth 2.0 是一個授權「框架」,裡面定義的都是抽象層次的規範,大致上會分作為兩個類型,一類是角色的定義,另一類是授權類型的定義。
OAuth 2.0 協定定義了參與授權流程的四個角色:
角色 | 說明 |
---|---|
Resource Owner | 資源擁有者,通常都是指「使用者」。 |
Resource Server | 資源伺服器,用來存放使用者受保護資源的伺服器。 |
Client | 應用程式,泛指對資源擁有者的資源有興趣的服務。 |
Authorization Server | 授權伺服器,專門用來處理授權的伺服器。 |
概念上來說,應用程式一開始都是無法「直接」地存取資源的,而是要透過授權伺服器來管理其存取行為。而在這流程中,使用者也有可能會需要參與授權流程,因為使用者通常是有權限管理資源的角色。應用程式必須經過使用者「同意」之後,才會發放憑證,應用程式就能透過憑證來存取資源。
一個實務的例子如:鐵人賽編輯器想做一個功能是能夠插入 Google 雲端硬碟上保存的圖片,但鐵人賽編輯器沒有直接存取參賽者 Google 雲端硬碟的權限,但可以透過 OAuth 2.0 流程來請求參賽者同意「鐵人賽編輯器存取參賽者放在 Google 雲端硬碟的檔案」。
在這個例子中角色對應如下:
而從上面的例子來看,授權流程的最終目標會是:應用程式能夠存取資源伺服器的資源。這個概念在 RFC 6749 - 1.2. Protocol Flow 裡有提到,文件有提出類似像下面的循序圖:
應用程式首先要發出授權請求給使用者,接著使用者同意授權後,應用程式會收到授權回應,內容有可能是同意授權,也有可能是其他錯誤。如果使用者同意授權的話,接著再拿同意授權的結果,來跟授權伺服器請求 Access Token--用來存取資源的憑證。應用程式取得 Access Token 之後,即可用來向資源伺服器驗證並請求存取資源。
了解角色和授權概念之後,接著要來了解這些角色可以如何互動。OAuth 2.0 提供了四個預定義的授權類型(Grant Type),同時也設計了擴充空間,讓未來在有其他需求的時候,還能夠方便新增流程,如 RFC 7521 - Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants 是利用 Assertion(如 SAML Assertion 或 JWT)來換取 Access Token 的框架。
這是常見也相較安全的授權類型,角色互動的時序圖如下:
這個流程有兩個關鍵:
因為 Authorization Code 授權流程設計上是完整且安全的,因此是目前 OAuth 2.0 主流的授權類型。
正如其名,在授權流程中有部分的流程是被隱含完成的,主要是在取得 Token 的步驟時,省略了驗證應用程式身分的流程。這容易讓 Access Token 有被「非應用程式身分」的攻擊者偷走的風險。現已被 OAuth 2.0 Security BCP 文件 為不應該(SHOULD NOT)使用的流程,目前大多數的情境都有對應的解法,但只剩 SPA(Single-Page Application,協定裡的專有術語是稱為 Browser-Based Application)有可能還需要使用 Implicit 授權模式,其他基本上都應該採用 Authorization Code 授權模式。
Implicit 流程時序圖如下:
問題主要在第 5 步:Access Token 放在 URI 的 Fragment 中。
雖然 HTTP 協定有提到請求資源的時候,不應該把 Fragment 包含在請求資源的一部分,但假設瀏覽器或伺服器沒有按照著這個協定實作的話,就有機會被中間人攻擊;另一方面,即便瀏覽器跟伺服器都有照著規範實作,因為 Fragment 依然是網址的一部分,Javascript 還是有辦法解析並取得 Access Token 的,若被 XSS 攻擊,Access Token 就有被偷的風險。
因為存在這些風險,因此 Implicit 被定為「不應該」使用的流程。
簡稱為 ROPC。這個授權類型與 Authorization Code 和 Implicit 一樣,會經由使用者授權,但不一樣的是:在這個流程裡,使用者不會經過授權伺服器,而是應用程式直接向使用者要求授權伺服器的驗證資訊來完成授權。
時序圖如下:
這個做法與最初提到的問題是類似的--應用程式會接收到使用者的帳號密碼,對使用者來說就會多一層風險。但使用帳密的方法是不同的,ROPC 是用帳密來交換 Access Token,後續存取資源就改用 Access Token,因此後續就不需要再儲存帳密,進而避免帳號密碼存明文的風險。
因為使用者的帳號密碼還是會需要經過應用程式,因此協定是建議這個授權類型僅用在應用程式是高度可信賴的時候,比方說應用程式是另一個子公司所開發的。
但是!事實上各種文章或是理論,都在說明 ROPC 授權類型存在非常多問題,包括 Hydra 也是,Hydra 並沒有也不打算實作 ROPC 授權類型,有部分與原生應用程式授權流程有關,這會留到未來的章節再來說明,其餘原因可以參考這篇文章。
應用程式直接跟授權伺服器做驗證,不透過使用者授權。時序圖如下:
主要應用在「應用程式本身就是資源擁有者」的情境,因此 Access Token 只能管理應用程式本身能管理的資源。像 GitHub 的 Personal Access Token 就是類似這樣的應用,只是它代表的是帳號的使用者本人,而不是應用程式。
今天說明了角色定義與四種基本授權類型的定義,明天接續來說明跟它關係很深的 OpenID Connecrt。